﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml;

namespace BuildCode.Models
{
    public class PDMReader : IDataBase
    {
        /// <summary>
        /// pdm文件路径
        /// </summary>
        private string pdmFilePath = "";
        /// <summary>
        /// pdm文件夹路径：Server.MapPath("~/PdmFiles/")
        /// </summary>
        private string pdmFilesDirectory = "";
        private static Dictionary<string, List<PDMColumnInfo>> dicTableColumns = new Dictionary<string, List<PDMColumnInfo>>();
        private static List<TableInfo> listTable;
        private static Dictionary<string, List<ColumnInfo>> dicTable;

        public void SetConfig(string _pdmFilesDirectory, string filePath)
        {
            pdmFilesDirectory = _pdmFilesDirectory;
            pdmFilePath = filePath;
        }

        public List<TableInfo> GetTableList()
        {
            if (listTable != null && listTable.Count > 0)
            {
                return listTable;
            }
            else
            {
                RefreshData();
                return listTable ?? new List<TableInfo>();
            }
        }

        public List<ColumnInfo> GetColumnList(string tableName)
        {
            if (dicTable.ContainsKey(tableName))
            {
                return dicTable[tableName];
            }
            else
            {
                RefreshData();
                return dicTable.ContainsKey(tableName) ? dicTable[tableName]: new List<ColumnInfo>();
            }
        }

        /// <summary>
        /// 刷新数据
        /// </summary>
        /// <returns></returns>
        public void RefreshData()
        {
            var listPdm = Directory.GetFiles(pdmFilesDirectory);
            var dic = new Dictionary<string, List<ColumnInfo>>();
            listTable = new List<TableInfo>();
            foreach (var path in listPdm)
            {
                var names = path.Split('.');
                if (names[names.Length - 1].ToLower() == "pdm")
                {
                    pdmFilePath = path;
                    var list = ReadFile();
                    foreach (var item in list)
                    {
                        var listCol = ReadColumns(item.TableName);
                        if (!dic.ContainsKey(item.TableName))
                        {
                            dic.Add(item.TableName, listCol);
                        }
                    }
                    listTable.AddRange(list);
                }
            }
            dicTable = dic;
        }

        private List<TableInfo> ReadFile()
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(pdmFilePath);
            XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(xmlDoc.NameTable);
            xmlnsManager.AddNamespace("a", "attribute");
            xmlnsManager.AddNamespace("c", "collection");
            xmlnsManager.AddNamespace("o", "object");
            XmlNode xnTables = xmlDoc.SelectSingleNode("//" + "c:Tables", xmlnsManager);

            List<PDMTableInfo> Tables = new List<PDMTableInfo>();
            foreach (XmlNode xnTable in xnTables.ChildNodes)
            {
                Tables.Add(GetTable(xnTable));
            }
            List<TableInfo> list = new List<TableInfo>();

            foreach (var m in Tables)
            {
                TableInfo entity = new TableInfo();
                entity.TableName = m.Code;
                entity.Comment = m.Name;
                list.Add(entity);
            }
            return list;
        }

        private List<ColumnInfo> ReadColumns(string tableName)
        {
            List<ColumnInfo> tableInfoList = new List<ColumnInfo>();
            List<PDMColumnInfo> list = new List<PDMColumnInfo>();
            if (dicTableColumns.ContainsKey(tableName))
            {
                list = dicTableColumns[tableName];
            }
            foreach (var m in list)
            {
                tableInfoList.Add(new ColumnInfo()
                {
                    ColumnName = m.Code.ToUpper(),
                    TypeName = m.DataType,
                    Comment = m.Name,
                    MaxLength = m.Length,
                    PropertyName = m.Code,
                    IsCheck = true,
                    IsDataColumn = true,
                    NotNUll = m.Mandatory
                }
                );
            }
            return tableInfoList;
        }

        //初始化"o:Table"的节点
        private PDMTableInfo GetTable(XmlNode xnTable)
        {
            PDMTableInfo mTable = new PDMTableInfo();
            XmlElement xe = (XmlElement)xnTable;
            mTable.TableId = xe.GetAttribute("Id");
            mTable.Columns = new List<PDMColumnInfo>();
            XmlNodeList xnTProperty = xe.ChildNodes;
            foreach (XmlNode xnP in xnTProperty)
            {
                switch (xnP.Name)
                {
                    case "a:ObjectID":
                        mTable.ObjectID = xnP.InnerText;
                        break;
                    case "a:Name":
                        mTable.Name = xnP.InnerText;
                        break;
                    case "a:Code":
                        mTable.Code = xnP.InnerText;
                        break;
                    case "a:CreationDate":
                        mTable.CreationDate = Convert.ToInt32(xnP.InnerText);
                        break;
                    case "a:Creator":
                        mTable.Creator = xnP.InnerText;
                        break;
                    case "a:ModificationDate":
                        mTable.ModificationDate = Convert.ToInt32(xnP.InnerText);
                        break;
                    case "a:Modifier":
                        mTable.Modifier = xnP.InnerText;
                        break;
                    case "a:Comment":
                        mTable.Comment = xnP.InnerText;
                        break;
                    case "a:PhysicalOptions":
                        mTable.PhysicalOptions = xnP.InnerText;
                        break;
                    case "c:Columns":
                        InitColumns(xnP, mTable);
                        break;
                    case "c:Keys":
                        InitKeys(xnP, mTable);
                        break;
                }
            }
            if (!dicTableColumns.ContainsKey(mTable.Code))
            {
                dicTableColumns.Add(mTable.Code, mTable.Columns.ToList());
            }
            return mTable;
        }
        //初始化"c:Columns"的节点
        private void InitColumns(XmlNode xnColumns, PDMTableInfo pTable)
        {
            foreach (XmlNode xnColumn in xnColumns)
            {
                pTable.AddColumn(GetColumn(xnColumn));
            }
        }

        //初始化c:Keys"的节点
        private void InitKeys(XmlNode xnKeys, PDMTableInfo pTable)
        {
            foreach (XmlNode xnKey in xnKeys)
            {
                pTable.AddKey(GetKey(xnKey));
            }
        }

        private PDMColumnInfo GetColumn(XmlNode xnColumn)
        {
            PDMColumnInfo mColumn = new PDMColumnInfo();
            XmlElement xe = (XmlElement)xnColumn;
            mColumn.ColumnId = xe.GetAttribute("Id");
            XmlNodeList xnCProperty = xe.ChildNodes;
            foreach (XmlNode xnP in xnCProperty)
            {
                switch (xnP.Name)
                {
                    case "a:ObjectID":
                        mColumn.ObjectID = xnP.InnerText;
                        break;
                    case "a:Name":
                        mColumn.Name = xnP.InnerText;
                        break;
                    case "a:Code":
                        mColumn.Code = xnP.InnerText;
                        break;
                    case "a:CreationDate":
                        mColumn.CreationDate = Convert.ToInt32(xnP.InnerText);
                        break;
                    case "a:Creator":
                        mColumn.Creator = xnP.InnerText;
                        break;
                    case "a:ModificationDate":
                        mColumn.ModificationDate = Convert.ToInt32(xnP.InnerText);
                        break;
                    case "a:Modifier":
                        mColumn.Modifier = xnP.InnerText;
                        break;
                    case "a:Comment":
                        mColumn.Comment = xnP.InnerText;
                        break;
                    case "a:DataType":
                        mColumn.DataType = xnP.InnerText;
                        break;
                    case "a:Length":
                        mColumn.Length = xnP.InnerText;
                        break;
                    case "a:Identity":
                        mColumn.Identity = ConvertToBooleanPG(xnP.InnerText);
                        break;
                    case "a:Mandatory":
                        mColumn.Mandatory = ConvertToBooleanPG(xnP.InnerText);
                        break;
                    case "a:PhysicalOptions":
                        mColumn.PhysicalOptions = xnP.InnerText;
                        break;
                    case "a:ExtendedAttributesText":
                        mColumn.ExtendedAttributesText = xnP.InnerText;
                        break;
                }
            }
            return mColumn;
        }

        private PDMKey GetKey(XmlNode xnKey)
        {
            PDMKey mKey = new PDMKey();
            XmlElement xe = (XmlElement)xnKey;
            mKey.KeyId = xe.GetAttribute("Id");
            XmlNodeList xnKProperty = xe.ChildNodes;
            foreach (XmlNode xnP in xnKProperty)
            {
                switch (xnP.Name)
                {
                    case "a:ObjectID":
                        mKey.ObjectID = xnP.InnerText;
                        break;
                    case "a:Name":
                        mKey.Name = xnP.InnerText;
                        break;
                    case "a:Code":
                        mKey.Code = xnP.InnerText;
                        break;
                    case "a:CreationDate":
                        mKey.CreationDate = Convert.ToInt32(xnP.InnerText);
                        break;
                    case "a:Creator":
                        mKey.Creator = xnP.InnerText;
                        break;
                    case "a:ModificationDate":
                        mKey.ModificationDate = Convert.ToInt32(xnP.InnerText);
                        break;
                    case "a:Modifier":
                        mKey.Modifier = xnP.InnerText;
                        break;
                        //还差 <c:Key.Columns>
                }
            }
            return mKey;
        }

        private static bool ConvertToBooleanPG(object obj)
        {
            if (obj != null)
            {
                string mStr = obj.ToString();
                mStr = mStr.ToLower();
                if ((mStr.Equals("y") || mStr.Equals("1")) || mStr.Equals("true"))
                {
                    return true;
                }
            }
            return false;
        }

        public string CheckConnection()
        {
            throw new NotImplementedException();
        }
    }

    public class PDMColumnInfo
    {
        public PDMColumnInfo()
        { }

        string columnId;

        public string ColumnId
        {
            get { return columnId; }
            set { columnId = value; }
        }
        string objectID;

        public string ObjectID
        {
            get { return objectID; }
            set { objectID = value; }
        }
        string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        string code;

        public string Code
        {
            get { return code; }
            set { code = value; }
        }
        int creationDate;

        public int CreationDate
        {
            get { return creationDate; }
            set { creationDate = value; }
        }
        string creator;

        public string Creator
        {
            get { return creator; }
            set { creator = value; }
        }
        int modificationDate;

        public int ModificationDate
        {
            get { return modificationDate; }
            set { modificationDate = value; }
        }
        string modifier;

        public string Modifier
        {
            get { return modifier; }
            set { modifier = value; }
        }
        string comment;

        public string Comment
        {
            get { return comment; }
            set { comment = value; }
        }
        string dataType;

        public string DataType
        {
            get { return dataType; }
            set
            {
                if (value.Contains("nvarchar") || value.Contains("varchar"))
                {
                    value = "string";
                }
                if (value.Contains("money"))
                {
                    value = "decimal";
                }
                dataType = value;
            }
        }
        string length;

        public string Length
        {
            get { return length; }
            set { length = value; }
        }
        //是否自增量
        bool identity;

        public bool Identity
        {
            get { return identity; }
            set { identity = value; }
        }
        bool mandatory;
        //禁止为空
        public bool Mandatory
        {
            get { return mandatory; }
            set { mandatory = value; }
        }
        string extendedAttributesText;
        //扩展属性
        public string ExtendedAttributesText
        {
            get { return extendedAttributesText; }
            set { extendedAttributesText = value; }
        }
        string physicalOptions;

        public string PhysicalOptions
        {
            get { return physicalOptions; }
            set { physicalOptions = value; }
        }
    }


    public class PDMKey
    {
        public PDMKey()
        {
        }

        string keyId;

        public string KeyId
        {
            get { return keyId; }
            set { keyId = value; }
        }
        string objectID;

        public string ObjectID
        {
            get { return objectID; }
            set { objectID = value; }
        }
        string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        string code;

        public string Code
        {
            get { return code; }
            set { code = value; }
        }
        int creationDate;

        public int CreationDate
        {
            get { return creationDate; }
            set { creationDate = value; }
        }
        string creator;

        public string Creator
        {
            get { return creator; }
            set { creator = value; }
        }
        int modificationDate;

        public int ModificationDate
        {
            get { return modificationDate; }
            set { modificationDate = value; }
        }
        string modifier;

        public string Modifier
        {
            get { return modifier; }
            set { modifier = value; }
        }

        IList<PDMColumnInfo> columns;

        public IList<PDMColumnInfo> Columns
        {
            get { return columns; }
        }

        public void AddColumn(PDMColumnInfo mColumn)
        {
            if (columns == null)
                columns = new List<PDMColumnInfo>();
            columns.Add(mColumn);
        }
    }


    public class PDMTableInfo
    {
        public PDMTableInfo()
        {
        }
        string tableId;

        public string TableId
        {
            get { return tableId; }
            set { tableId = value; }
        }
        string objectID;

        public string ObjectID
        {
            get { return objectID; }
            set { objectID = value; }
        }
        string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        string code;

        public string Code
        {
            get { return code; }
            set { code = value; }
        }
        int creationDate;

        public int CreationDate
        {
            get { return creationDate; }
            set { creationDate = value; }
        }
        string creator;

        public string Creator
        {
            get { return creator; }
            set { creator = value; }
        }
        int modificationDate;

        public int ModificationDate
        {
            get { return modificationDate; }
            set { modificationDate = value; }
        }
        string modifier;

        public string Modifier
        {
            get { return modifier; }
            set { modifier = value; }
        }
        string comment;

        public string Comment
        {
            get { return comment; }
            set { comment = value; }
        }

        string physicalOptions;

        public string PhysicalOptions
        {
            get { return physicalOptions; }
            set { physicalOptions = value; }
        }


        IList<PDMColumnInfo> columns;

        public IList<PDMColumnInfo> Columns
        {
            get { return columns; }
            set { columns = value; }
        }

        IList<PDMKey> keys;

        public IList<PDMKey> Keys
        {
            get { return keys; }
        }

        public void AddColumn(PDMColumnInfo mColumn)
        {
            if (columns == null)
                columns = new List<PDMColumnInfo>();
            columns.Add(mColumn);
        }

        public void AddKey(PDMKey mKey)
        {
            if (keys == null)
                keys = new List<PDMKey>();
            keys.Add(mKey);
        }
    }
}